package com.luo.d3s.anti.mvc.ec.service.impl;

import com.luo.d3s.anti.mvc.ec.dao.OrderGoodsMapper;
import com.luo.d3s.anti.mvc.ec.dao.OrderMapper;
import com.luo.d3s.anti.mvc.ec.model.dto.OrderCreateDto;
import com.luo.d3s.anti.mvc.ec.model.dto.OrderDeliverDto;
import com.luo.d3s.anti.mvc.ec.model.event.OrderPaidEvent;
import com.luo.d3s.anti.mvc.ec.model.dto.OrderPageQueryDto;
import com.luo.d3s.anti.mvc.ec.entity.Order;
import com.luo.d3s.anti.mvc.ec.entity.OrderGoods;
import com.luo.d3s.anti.mvc.ec.enums.OrderStatus;
import com.luo.d3s.anti.mvc.ec.rpc.PaymentRpc;
import com.luo.d3s.anti.mvc.ec.rpc.StockRpc;
import com.luo.d3s.anti.mvc.ec.service.OrderService;
import com.luo.d3s.anti.mvc.ec.model.vo.OrderVo;
import com.luo.d3s.core.application.dto.PageResponse;
import com.luo.d3s.core.application.dto.Response;
import com.luo.d3s.core.application.dto.SingleResponse;
import com.luo.d3s.core.util.IdGenUtils;
import com.luo.d3s.core.util.validation.Validates;
import com.luo.d3s.ext.event.jdbc.EventBus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 订单服务实现类
 *
 * @author luohq
 * @date 2022-11-27 19:16
 */
@Service
public class OrderServiceImpl implements OrderService {

    @Resource
    private OrderMapper orderRepository;

    @Resource
    private OrderGoodsMapper orderGoodsMapper;

    @Resource
    private PaymentRpc paymentRpc;

    @Resource
    private StockRpc stockRpc;


    @Override
    public SingleResponse<OrderVo> findOrder(Long orderId) {
        OrderVo orderVo = this.orderRepository.findVoById(orderId);
        return SingleResponse.of(orderVo);
    }

    @Override
    public PageResponse<OrderVo> findOrderPage(OrderPageQueryDto orderPageQueryDto) {
        return this.orderRepository.findPage(orderPageQueryDto);
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public SingleResponse<Long> createOrder(OrderCreateDto orderCreateDto) {
        //生成新的订单ID
        Long orderId = IdGenUtils.nextDigitalId();
        //创建订单
        Order order = new Order();
        order.setId(orderId);
        order.setOrderPrice(orderCreateDto.getOrderPrice());
        order.setReceiveAddress(orderCreateDto.getReceiveAddress());
        order.setOrderStatus(OrderStatus.CREATED.getValue());
        //持久化订单
        this.orderRepository.insert(order);

        //创建订单商品列表
        List<OrderGoods> orderGoodsList = orderCreateDto.getOrderGoods().stream()
                .map(orderGoodsDto -> {
                    OrderGoods orderGoods = new OrderGoods();
                    orderGoods.setGoodsId(orderGoodsDto.getGoodsId());
                    orderGoods.setOrderId(orderId);
                    orderGoods.setGoodsCount(orderGoodsDto.getGoodsCount());
                    orderGoods.setGoodsPrice(orderGoodsDto.getGoodsPrice());
                    orderGoods.setGoodsSumPrice(orderGoodsDto.getGoodsSumPrice());
                    return orderGoods;
                })
                .collect(Collectors.toList());
        //批量保存商品订单列表
        orderGoodsList.forEach(this.orderGoodsMapper::insert);

        // 锁库存
        this.stockRpc.lockStock(order);
        return SingleResponse.of(order.getId());
    }


    @Transactional(rollbackFor = Throwable.class)
    @Override
    public Response payOrder(Long orderId) {
        Order order = this.orderRepository.selectById(orderId);
        Validates.notNull(order, "order not exist!");
        Validates.isTrue(OrderStatus.CREATED.getValue().equals(order.getOrderStatus()), "order status is not CREATED");
        // 调用第三方支付系统支付订单
        this.paymentRpc.payOrder(order);
        //修改订单支付状态
        order.setOrderStatus(OrderStatus.PAID.getValue());
        order.setPayTime(LocalDateTime.now());
        order.setUpdateTime(LocalDateTime.now());
        //更新订单
        this.orderRepository.updateById(order);
        //发送订单已支付事件
        EventBus.publish(new OrderPaidEvent(order));
        return Response.buildSuccess();
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public Response deliverOrder(OrderDeliverDto orderDeliverDto) {
        Order order = this.orderRepository.selectById(orderDeliverDto.getOrderId());
        Validates.notNull(order, "order not exist!");
        Validates.isTrue(OrderStatus.PAID.getValue().equals(order.getOrderStatus()), "order status is not PAID");
        //修改订单已发货状态
        order.setOrderStatus(OrderStatus.DELIVERED.getValue());
        order.setExpressCode(orderDeliverDto.getExpressCode());
        order.setDeliverTime(orderDeliverDto.getDeliveryTime());
        order.setUpdateTime(LocalDateTime.now());
        //更新订单
        this.orderRepository.updateById(order);
        return Response.buildSuccess();
    }


    @Transactional(rollbackFor = Throwable.class)
    @Override
    public Response completeOrder(Long orderId) {
        Order order = this.orderRepository.selectById(orderId);
        Validates.notNull(order, "order not exist!");
        Validates.isTrue(OrderStatus.DELIVERED.getValue().equals(order.getOrderStatus()), "order status is not DELIVERED");
        //修改订单完成状态
        order.setOrderStatus(OrderStatus.COMPLETED.getValue());
        order.setCompleteTime(LocalDateTime.now());
        order.setUpdateTime(LocalDateTime.now());
        //更新订单
        this.orderRepository.updateById(order);
        return Response.buildSuccess();
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public Response cancelOrder(Long orderId) {
        Order order = this.orderRepository.selectById(orderId);
        Validates.notNull(order, "order not exist!");
        //修改订单已取消状态
        order.setOrderStatus(OrderStatus.CANCELED.getValue());
        order.setCancelTime(LocalDateTime.now());
        order.setUpdateTime(LocalDateTime.now());
        //更新订单
        this.orderRepository.updateById(order);
        return Response.buildSuccess();
    }
}
